#include "glwidget.h"
#include <QtMath>

GLWidget::GLWidget(QWidget *parent, bool fs)
    : QGLWidget(parent)
{
    fullscreen = fs;
    setGeometry(0,0, 640, 480);
//    setCaption("");
    if (fullscreen) {
        showFullScreen();
    }
}

GLWidget::~GLWidget()
{

}

/**
 * @brief Widget::initializeGL - 对opengl进行初始化设置，该函数直到窗口创建之后才会被调用
 */
void GLWidget::initializeGL()
{
    /*启用阴影平滑。阴影平滑通过多边形精细的混合色彩，并对外部光进行平滑*/
    glShadeModel( GL_SMOOTH );

    /*设置清除屏幕时所用的颜色。色彩值的范围从0.0到1.0. 0.0代表最黑的情况，1.0代表最亮的情况*/
    glClearColor(0.0, 0.0, 0.0, 0.0);

    /*设置深度缓存*/
    glClearDepth(1.0);
    /*启用深度测试*/
    glEnable( GL_DEPTH_TEST );
    /*设置深度测试的类型*/
    glDepthFunc( GL_LEQUAL );

    /*真正精细的透视修正, 这会十分轻微的影响性能，但使用透视图看起来好一点*/
    glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
}

/**
 * @brief Widget::paintGL  -  包括所有绘图代码。任画图的代码都要在这个函数里实现
 */
void GLWidget::paintGL()
{
    qDebug("%s[%d]", __func__, __LINE__);
    /*清除屏幕和深度缓存*/
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    /*重置当前的模型观察矩阵,将当前点移到屏幕中心，
     * X坐标轴从左到右，Y坐标轴从下到上，z坐标轴从外到里，
     * 屏幕中心的坐标值为（0，0）*/
    glLoadIdentity();

//    glBegin( GL_QUADS );
//    GLfloat f = 1;
//    glVertex3f( -f, f, 0.0 );   //右上角
//    glVertex3f( f, f, 0.0 );    //右下角
//    glVertex3f( f, -f, 0.0 );   //左上角
//    glVertex3f( -f, -f, 0.0 );  //左下角
//    glEnd();
//    return;

    /*X轴左移0.3个单位， Y轴上移0.3个单位， Z轴移入屏幕0.6个单位，不是相对屏幕中心移动，而是相对当前所在屏幕位置*/
    glTranslatef(-0.3, 0.3, -0.6);

    /*设置填充颜色为红色*/
    glColor3f( 1.0, 0.0, 0.0 );

    /*创建三角形*/
    glBegin( GL_TRIANGLES );
    /*设置三个顶点, 如果想创建多个三角形，可以多个三个顶点集合*/
    glVertex3f( 0.0, 0.2, 0.0 );    //上顶点
    glVertex3f( -0.2, -0.2, 0.0);   //左下顶点
    glVertex3f( 0.2, -0.2, 0.0);    //右下顶点
    /*三角形绘制结束*/
    glEnd();

    glTranslatef( 0.6, 0.0, 0.0);
    /*创建四边形*/
    glBegin( GL_QUADS );
    /*设置四个顶点*/
    glVertex3f( -0.2, 0.2, 0.0 );   //左上顶点
    glVertex3f( 0.2, 0.2, 0.0 );    //右上顶点
    glVertex3f( 0.2, -0.2, 0.0 );   //右下顶点
    glVertex3f( -0.2, -0.2, 0.0 );  //左下顶点
    glEnd();

    glLoadIdentity();
    glTranslatef(0.0f, -0.3f, 0.0f);
    glColor3f(0.0f, 0.0f, 1.0f);
    /*这里用连续的三角形面积来逼近圆的面积实现圆周的画法*/
    GLint circle_points = 100;
    glBegin(GL_TRIANGLE_FAN);
    for(int i = 0; i < circle_points; i++ )
    {
        double angle = 2*M_PI*i/circle_points;
        glVertex3d(0.2*cos(angle), 0.2*sin(angle), 0);
    }
    glEnd();
}

/**
 * @brief Widget::resizeGL  -  重新设置Opengl场景的大小。与窗口大小不是一个概念
 * @param width     场景宽度
 * @param height    场景高度
 */
void GLWidget::resizeGL(int width, int height)
{
    int side = qMin(width, height);
    qDebug("w:h [%d:%d]", width, height);
    if (0 == height) {
        /*防止height为0*/
        height = 1;
    }

    /*重置当前的视口*/
    glViewport(0, 0, (GLint)width, (GLint)height);

    /*选择投影矩阵*/
    glMatrixMode( GL_PROJECTION );
    /*重置投影矩阵*/
    glLoadIdentity();

    /*建立透视投影矩阵，Qt4.8以后都不支持glu开头的函数*/
//    gluPerspective( 45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);

    /*选择模型观察矩阵*/
    glMatrixMode( GL_MODELVIEW );
    /*重置模型观察矩阵*/
    glLoadIdentity();

    /*keep sharp*/
    glViewport((width - side) / 2, (height - side) / 2, side, side);
}

void GLWidget::keyPressEvent(QKeyEvent *e)
{
    switch (e->key()) {
    case Qt::Key_F2:
        fullscreen = !fullscreen;
        if (fullscreen) {
            showFullScreen();
        } else {
            showNormal();
            setGeometry(0,0, 640, 480);
        }
        updateGL();
        break;
    case Qt::Key_Escape:
        close();
        break;
    default:
        break;
    }
}
